using AForge.Video.FFMPEG;
using Clancy.Common;
using Clancy.Interfaces;
using System;
using System.Drawing;
using System.IO;
using System.Threading;

namespace Clancy.Bl.Surveilance
{
    public class SurveilanceVideoFileWriter
    {
        private readonly Action<ISurveilanceObject, string> m_CreateNewRecordingCallback;
        private readonly ISurveilanceResultFrame[] m_FramesToWrite;
        private readonly string m_TargetDirectory;
        private ISurveilanceObject m_SurveilanceObject;

        public SurveilanceVideoFileWriter(ISurveilanceObject surveilanceObject, ISurveilanceResultFrame[] currentFrames, Action<ISurveilanceObject, string> createNewRecordingCallback)
        {
            m_SurveilanceObject = surveilanceObject;
            m_TargetDirectory = surveilanceObject.RecordBaseDirectory;
            m_FramesToWrite = currentFrames;
            m_CreateNewRecordingCallback = createNewRecordingCallback;

            if ((!string.IsNullOrEmpty(m_TargetDirectory)) && (!m_TargetDirectory.EndsWith("\\")))
                m_TargetDirectory = string.Format("{0}\\", m_TargetDirectory);
        }

        public void WriteVideoFile()
        {
            ThreadPool.QueueUserWorkItem(WriteVideoFile);
        }

        private void WriteVideoFile(object surveilanceResultFrames)
        {
            if (m_FramesToWrite == null)
                return;

            if (m_FramesToWrite.Length < 2)
                return;

            if (string.IsNullOrEmpty(m_TargetDirectory))
                return;

            if (!Directory.Exists(m_TargetDirectory))
            {
                Directory.CreateDirectory(m_TargetDirectory);
            }

            string filename = string.Format("{0}{1}.avi", m_TargetDirectory, m_FramesToWrite[0].Timestamp.ToString("yyyy-MM-dd_hh-mm-ss"));

            TimeSpan duration = m_FramesToWrite[m_FramesToWrite.Length - 1].Timestamp - m_FramesToWrite[0].Timestamp;
            double framerate = m_FramesToWrite.Length / duration.TotalSeconds;

            using (VideoFileWriter writer = new VideoFileWriter())
            {
                Bitmap firstFrame = m_FramesToWrite[0].Frame.ToBitmap();
                writer.Open(filename, firstFrame.Width, firstFrame.Height, (int)framerate, VideoCodec.MPEG4);

                DateTime startTime = new DateTime(0);
                foreach (ISurveilanceResultFrame frame in m_FramesToWrite)
                {
                    if (startTime.CompareTo(new DateTime(0)) == 0)
                        startTime = frame.Timestamp;

                    TimeSpan currentFrameTime = frame.Timestamp - startTime;
                    writer.WriteVideoFrame(frame.Frame.ToBitmap(), currentFrameTime);
                }

                writer.Close();
            }

            if (m_CreateNewRecordingCallback != null)
            {
                m_CreateNewRecordingCallback.Invoke(m_SurveilanceObject, filename);
            }
        }
    }
}